#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Auth: 张宇飞(zhangyufei49@163.com)
Date: 2017-09-19
Desc: pitch 和 note 相互转换
"""

def parse_args():
    import sys
    if len(sys.argv) < 2:
        return None

    ret = []
    for arg in sys.argv[1:]:
        ret.append(arg.lower())
    return ret

def convert(arg):
    sylables_sharp = ["C", "#C", "D", "#D", "E", "F", "#F", "G", "#G", "A", "#A", "B"]
    sylables_flat = ["C", "bD", "D", "bE", "E", "F", "bG", "G", "bA", "A", "bB", "B"]

    def format_note(note):
        if len(note) > 2:
            return note[0] + note[1:].upper()
        else:
            return note[0].upper() + note[1:]

    def pitch_to_note(pitch):
        syllable = pitch % 12
        n = int(pitch // 12 - 1)
        sharp = sylables_sharp[syllable]
        flat = sylables_flat[syllable]
        if sharp == flat:
            return "%s%d" % (sharp, n)
        else:
            return "%s%d(%s%d)" % (sharp, n, flat, n)

    def note_to_pitch(note):
        n = (int(note[-1]) + 1) * 12
        try:
            idx = sylables_sharp.index(note[:-1])
            return idx + n
        except Exception as e:
            pass

        idx = sylables_flat.index(note[:-1])
        return idx + n

    def convert_from_num(n, m):
        dec_pitch = int(n, m)
        hex_pitch = hex(dec_pitch)
        note = pitch_to_note(dec_pitch)
        return (note, dec_pitch, hex_pitch)

    l = len(arg)
    if l == 1: # 整数方式解析
        return convert_from_num(arg, 10)
    elif arg[:2] == "0x":
        return convert_from_num(arg, 16)
    elif ord(arg[0]) >= ord('0') and ord(arg[0]) <= ord('9'):
        return convert_from_num(arg, 10)
    else:
        return convert_from_num(str(note_to_pitch(format_note(arg))), 10)


def format_print(info):
    print("note: %-10sdec: %-10dhex: %s" % (info[0], info[1], info[2]))

def show_help():
    import sys
    from os.path import basename

    program_name = basename(sys.argv[0])
    title = "%s| %s |%s" % ("-" * 20, program_name, "-" * 20)

    print(title)
    print("""
用于转换 pitch 和 note 音符

Usage: %s <pitch | note> [pitch | note] ...

Example:
    %s c4 C5 48 0x3c 0x2A

    """ % (program_name, program_name))
    print("-" * len(title))

def main():
    args = parse_args()
    if args == None:
        show_help()
        exit(1)

    for arg in args:
        format_print(convert(arg))

if __name__ == "__main__":
    main()
